package com.AdvancedDemos.泛型;

import java.util.ArrayList;

public class GenericMethod {
    public static void main(String[] args) {
        //泛型函数并非泛型类中使用泛型类型的成员函数,而是一个单独的带泛型的函数
        System.out.println(test("name"));//public static <E> String test(String e),自动识别泛型E为String类型
        System.out.println(test(new Dog()));//public static <E> Dog test(Dog e),传Dog对象则E成了Dog类型


        //----------------------------

        ArrayList<Car> cars = new ArrayList<>();
        cars.add(new BMW());
        cars.add(new BENZ());
        go(cars);

        ArrayList<BMW> bmws = new ArrayList<>();
        bmws.add(new BMW());
        bmws.add(new BMW());
//        go(bmws);//报错,BMW是Car的子类,但是ArrayList<BMW>与ArrayList<Car>并没有关系
        go(bmws);

        ArrayList<BENZ> benzs = new ArrayList<>();
        benzs.add(new BENZ());
        benzs.add(new BENZ());
//        go(benzs);//报错,同理
        go(benzs);

        ArrayList<Dog> dogs = new ArrayList<>();
        dogs.add(new Dog());
        dogs.add(new Dog());
        //        go(dogs);
        // 需要的类型:
        //ArrayList <T>
        //提供的类型:
        //ArrayList <Dog>
        //原因: 不存在类型变量的实例，使 Dog 符合 Car


        //------------------------------
        //泛型函数做形参时使用 ? 通配符
        ArrayList<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        isEqual(list);//并不会把形参中的泛型变成<String>类型,<?>通配符只表示可以接任何类型的对象,自身并不会变,因为不确定<?>到底是什么类型,所以list.get(0)的返回值是Object类型,此时只能调用Object类型中的函数,如o.equals(o1),其他子类特有的函数都不能使用


    }


    public static void isEqual(ArrayList<?> list) {
        Object o = list.get(0);
        Object o1 = list.get(1);
        System.out.println(o.equals(o1));
    }


    /*
     * 泛型函数
     *
     * 修饰符<类型变量,类型变量,...> 返回值类型 方法名(形参列表){
     *
     * }
     */
    //例如:
    public static <E> E test(E e) {//E的实际类型由编译器自动根据实参类型判断
        return e;
    }


    //----------------------------

    //    public static <T extends Car> void go(ArrayList<T> list) {//使用泛型来允许接受各种类型,使用extends限制只能是Car或其子类
    public static void go(ArrayList<? extends/*super*/ Car> list) {//可以不自己定义泛型,使用 ? 通配符,在形参中需要泛型时可以代表一切类型,额外再加上extends Car可以限制泛型只能是Car或其向下继承的子类(即Car成为上限),如果是ArrayList<? super Car> list则表示ArrayList的泛型只能是Car或Car的向上继承的父类(即Car成为下限)
    }


}


class Car {

}

class BMW extends Car {

}

class BENZ extends Car {

}


